package com.atguigu.reflect;

public class Demo06ClassInfo {

//    @Test
//    public void testGetPackage() {
//        // 获取一个类所在的包
//        Package packageOfTiger = Tiger.class.getPackage();
//        System.out.println("packageOfTiger = " + packageOfTiger);
//
//        String name = packageOfTiger.getName();
//        System.out.println("name = " + name);
//    }
//
//    @Test
//    public void testGetModifier() {
//        // 获取类的修饰信息
//        // modifiers 值是怎么来的？
//        // 各个具体的修饰符在 Modifier 类中声明了一个常量
//        // PUBLIC       0000 0001
//        // PRIVATE      0000 0010
//        // PROTECTED    0000 0100
//        // STATIC       0000 1000
//        // FINAL        0001 0000
//        // ……
//        // 各个常量转换为二进制数之后，所有二进制位中只有一个二进制是 1
//        // 假设某个类的声明是：
//        // public static final class Xxx
//        // 0000 0001
//        // 0000 1000
//        // 0001 0000       |
//        // ---------------------
//        // 0001 1001 ----> 这就是 modifiers 这个值
//        // 『投影』之后，一个整数值就能够表达丰富的信息
//        // 运算举例：(mod & PUBLIC) != 0
//        // 0001 1001
//        // 0000 0001 &
//        // ------------------
//        // 0000 0001
//        int modifiers = Tiger.class.getModifiers();
//
//        boolean isPublic = Modifier.isPublic(modifiers);
//        System.out.println("isPublic = " + isPublic);
//
//        boolean isPrivate = Modifier.isPrivate(modifiers);
//        System.out.println("isPrivate = " + isPrivate);
//    }
//
//    @Test
//    public void testGetMethodModifier() throws NoSuchMethodException {
//        Method method = Tiger.class.getDeclaredMethod("getTigerName");
//
//        int modifiers = method.getModifiers();
//
//        boolean isFinal = Modifier.isFinal(modifiers);
//        System.out.println("isFinal = " + isFinal);
//    }
//
//    @Test
//    public void testClassName() {
//        String name = Tiger.class.getName();
//        System.out.println("name = " + name);
//
//        String typeName = Tiger.class.getTypeName();
//        System.out.println("typeName = " + typeName);
//
//        String comparableName = Comparable.class.getName();
//        System.out.println("comparableName = " + comparableName);
//    }
//
//    @Test
//    public void testGetSuperClass() {
//        // 获取父类的 Class 对象
//        Class<? super Tiger> superclass = Tiger.class.getSuperclass();
//
//        System.out.println("superclass = " + superclass);
//    }
//
//    @Test
//    public void testGetSuperInterface() {
//        Class<?>[] interfaces = Tiger.class.getInterfaces();
//        for (Class<?> anInterface : interfaces) {
//            System.out.println("anInterface = " + anInterface);
//        }
//    }
//
//    @Test
//    public void testGetInnerClass() {
//        Class<?>[] declaredClasses = Tiger.class.getDeclaredClasses();
//        for (Class<?> declaredClass : declaredClasses) {
//            System.out.println("declaredClass = " + declaredClass);
//        }
//    }
//
//    @Test
//    public void testGetGenericType() {
//        // 创建对象时指定了泛型
//        Cat<String> cat = new Cat<>();
//        Cat<Integer> cat02 = new Cat<>();
//
//        // 能否通过反射获取泛型类型？
//        Class<? extends Cat> catClass = cat.getClass();
//
//        Type[] genericInterfaces = catClass.getGenericInterfaces();
//        for (Type genericInterface : genericInterfaces) {
//            // java.lang.Comparable<java.lang.String>
//            System.out.println("genericInterface = " + genericInterface);
//        }
//
//        // 通过上述代码的测试，我们发现：如果想要通过反射获取到泛型类型，那么这个泛型类型就必须是确定的才可以
//    }
//
//    @Test
//    public void testGetSuperClassGenericType() {
//        // 思路：子类继承父类时，可以传入确定的泛型参数，同时这个确定的泛型参数会被写入子类编译出来的字节码文件
//        // 结论：我们可以通过子类来获取父类的泛型参数
//        // 辨析：如何区分 Type 和 Class 代表的含义？
//        // Type 代表『类型』的概念，凡是能用来修饰变量的都算类型，包括类和接口
//        // Class 代表『类』
//        Type genericSuperclassType = Tiger.class.getGenericSuperclass();
//
//        // ParameterizedType 的意思是『参数化的类型』
//        ParameterizedType parameterizedType = (ParameterizedType) genericSuperclassType;
//
//        // 进一步获取类型的参数
//        // actual：实际的，真实的
//        // actualTypeArguments：实际的类型参数组成的数组
//        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
//
//        for (Type actualTypeArgument : actualTypeArguments) {
//            System.out.println("actualTypeArgument = " + actualTypeArgument);
//        }
//    }
}
